MechWarrior 2
Artificial Intelligence

Activision
Copyright 1995-1997 Activision
http://www.activision.com

Last updated: 10 Jan 1997
The original copy of this document is located at http://www.activision.com/mercnet/mercai.htm.

NOTE: These information is provided as is with no claims made as to accuracy or usefulness. WE WILL NOT RESPOND TO ANY QUESTIONS REGARDING THE TOOL SET ON OUR CUSTOMER SUPPORT LINES OR ON-LINE SUPPORT ACCOUNTS.

Table of Contents

Introduction

The Artificial Intelligence (AI) engine for Mechwarrior 2 is a highly complex and versatile system for directing the actions of computer-controlled adversaries. At the highest level, game AI starts with the mission objective (MO) code which processes the mission table, the table which scripts the main actions and outcomes for each mission. Beneath the MO code is the general level AI, discussed here, which controls behavior of groups of gamepieces as well as individual gamepieces. This general level AI is further split into non-combat and combat (tactical) AI. The first discussion below covers the general, non-combat AI and is followed by a discussion of the tactical AI.

Note: the only knobs available to the mission designer are the old Gunnery Skill, Piloting Skill, Targeting Range, Sleep Range and Rubberband Range fields in the gp_spec line of the .wld file, as well as the new Affiliation Type and Personality fields of the gp_spec and the Disturb Level and Mechs Per Target fields of the mission objective tables.

This document discusses the internals of the AI engine in greater detail than the mission developer truly needs. However, the more a mission developer knows about the AI, the more likely he or she will be able to develop great single-player missions.

Note: the DOS sim has a -M commandline option which displays various pieces of information about the current state of the AI on a monochrome monitor. This is very helpful for debugging AI behavior. Do not use the -M switch if you do not have a monochrome adapter and monitor.

General AI

The general AI implementation is based on a system of "states". Gamepieces are always in one of many states, and can be made to change state based on information about the world around them. At the lowest level is a common state table which is scripted as an ASCII text file and compiled using the proprietary AIPARSER.EXE. Note: These tables are fixed, and cannot be changed by the mission developer.

AI Tables

AI tables are created as individual text files, then parsed using the AIPARSER tool which generates an AI specific formatted binary file that is added to the project file. The AI code is designed to handle up to three levels of tables, with each level having the ability extend or override behavior in a successive (lower) level. The lowest level table, the default table, describes the default behavior for any gamepiece using that set of tables and so should specify all states which that gamepiece is capable of having. In fact, the tables can be structured any way desired as long as every possible state for a gamepiece is specified in at least one of the three tables. The intent behind having the three table groups was originally as follows:

As implemented, only the Global (default) and Individual tables are used, as it was possible to specify all necessary behavior in just those two tables. Had we chosen to implement a greater variety of AI based on other factors, such as gamepiece class, mech type, or even clan, the Group table could have been used as well.

Also as implemented, the global table is always initialized to a single table called «DEFLT». The individual tables are assigned based on two attributes: a gamepiece's leader/follower classification, and the current star objective (e.g. defend, recon, etc...). Hence, individual tables have names like «LDESTROY» (Leader Destroy), and «FDEFEND» (Follower Defend). Internally, all tables are loaded at world loader time but are assigned dynamically during game play as a star's objective changes and as an individual mech's position within his star changes (i.e. going from follower to leader).

The tables are searched from the individual up to the global level. Whereas the global table should probably contain the default behavior for all the states a Gamepiece is capable of, a group or individual table will "override" that intelligence by providing alternative behavior for the same states. Thus, individual tables contain the least data with the bulk of AI information being left to the group and global tables. Group and individual tables can also «extend» the functionality of the global table by including additional states, but in practice, individual tables were used only to override.

State Table Format

Rather than base the AI on a distributive, message based model where decision routines gather information and send messages to the gamepieces, this model calls for each gamepiece to poll a list of conditionals specified by its state and take the appropriate action described in the table. Although this document uses the term "messages" when referring to these state change motivations they are, in fact, "conditions" which each Gamepiece polls through his AI loop and acts upon should any one of them evaluate to true.

Each line in a state table looks like this:
<stateName (optional)> <msg.> <obj. ref.> <msg. param> <trans. action> <New state> <state arg.>

Here's an example of a state with two transition specifications:

Target  M_PROX,    '@',  350,   T_NULL, Attack,  '%'
        M_DESTROY, '@',  0,     T_POP,  follow,  agp_myleader
This is read roughly as follows: When an AI-controlled character is in Target state,
  1. if the current target is within 350 meters, jump to Attack state
  2. else if the current target has been destroyed, pop the previous state off the stack; if there was no state saved, jump to Follow state.

If the stateName is given, this is the first line of that state, if no stateName is given, it is the next line of the current state. Each of the lines is a "transition specification" which describes a conditional test, along with a course of action should that test evaluate to TRUE. Every state in a table has one or more lines; each line is a transition specification. Each line consists of

  1. the state name (optional; only on first line of state),
  2. a message (the conditional),
  3. an object reference and message parameter (the arguments to the conditional),
  4. a transition action (what should happen if the conditional is true; can save or restore the previous state or defer the entire message).
  5. a transition state (what new state to jump to if the conditional is true and the transition action allows it),
  6. and a state argument (the object of the new state),
Each time through an object's AI loop, the row corresponding to the object's current state is traversed and each conditional is tested. The object's proximity to an enemy, or whether or not it has reached it's destination are two examples. When any condition is found to be true, specified transition is performed and AI processing for that gamepiece is ended for that cycle. Since it is possible for more than one condition within a conditional group to be true and since the first condition encountered which evaluates to true ceases further evaluation, the ordering of these conditions within their group provides an implicit priority which adds an additional level of "intelligence" to the table itself.

States

Each computer-controlled player is in one of the following ten states at any time. The names of these states appear in two places in the state table: as labels in the first column indicating the beginning of a state table, and in the sixth column, indicating the state to go to if the conditional is true.

(There are other states defined, but not implemented.)

Messages

The conditional part of the state table is called a Message. When a Message succeeds, the value of the object (which can not be NULL) is returned, and table processing terminates. If the Messages fails, NULL is returned, and table processing continues.

The possible values are:

Object Reference

Though any explicit reference to a gamepiece, gamething, or navpoint may be entered here, more often this field is used with a value that must be resolved upon entry to a state. This resolution happens immediately upon entrance to the state, so the gamepiece always has a valid target.

The possible values are:

Message Parameter

Usually (always?) a distance value.

The possible values are:

Transition Action

If the Message evaluates to true, the specified function is called before the state changes.

The possible values are:

State Argument

This value will be passed along to the next state, where it will appear if the Object Reference is '@'. The State Argument is always some sort of reference to a world object, either resolved or unresolved.

The possible values for state arg. are:

Multiple messages

The ability for each "state" to have more than one "message" of the same type allows for multiple specifications of the same message, with different arguments and outcomes, within a given state. For example, if a friendly Gamepiece is in proximity (M_PROX) to a hostile Gamepiece, it might perform a combat related action. However, if the same Gamepiece comes within M_PROX of the user's Gamepiece, it might revert to a protective patrol mode.

To allow for a more flexible message specification each "state" in the table can have a different number of "messages" of any type; the total width of the table being equal to the maximum number of messages in any state.

Transitions

When a state change is made using the table, a "Transition" action is called prior to an actual state change. These functions return a Boolean value which dictates whether the state change is to take place or not. Transition actions always perform functions directly related to the state table itself, never to anything outside the table. Common applications of transition actions include saving the current state, remembering a previous state, passing the current message on to another Gamepiece, clearing the AI stack, and doing nothing at all.

Message passing

Gamepieces have the ability to send messages directly to other Gamepieces. Usually this will occur when a T_NOTIFY message from the table returns TRUE. When this occurs the Gamepiece will pass on the entire message to the leader, who will evaluate it the next time he becomes active, and decide upon a proper course of action.

State Table Examples

The following table snippet containing two states, "Target" and "Attack", implements the default behavior for a gamepiece that allows it to handle an order to target and attack an object.
Target  M_PROX,    '@',          350,     T_NULL, Attack,   '%'
        M_DESTROY, '@',          0,       T_POP,  follow,   agp_myleader
        M_DIST,    agp_rbanchor, &r,      T_POP,  godirect, '%'

Attack  M_DESTROY, '@',          0,       T_POP,  follow,   agp_myleader
        M_DIST,    agp_rbanchor, &r,      T_POP,  godirect, '%'
        M_DIST,    '@',          350,     T_NULL, target,   '%'

While in the "target" state, the AI code by default will try to go to the current target; then the list of conditionals is traversed from top to bottom starting with the M_PROX.

In this case, M_PROX evaluates to TRUE only if we are 350 meters or less from our current target '@'. If we are, then the transition function T_NULL is executed and, since it does nothing but evaluate to FALSE, causes us to transition to the Attack state using the '%' symbolic reference to whatever argument was fed to the current conditional, namely our current target.

If we haven't reached our target, the M_DESTROY checks to see if we've destroyed our current target, and attempts to POP back to our previous state if so. If we have no previous state (thus T_POP returns FALSE), then we default to following our leader.

The final conditional under Target is the M_DIST which, in this case, checks to see that we haven't strayed too far from our anchor position. The anchor position represents a navpoint which we've placed at some point in the past and it is used to keep a mech from being lured away from his star (historically to prevent too many mechs from being on screen at a time, but practically not really a big deal). If we have strayed too far, we'll attempt to T_POP back to our previous state, defaulting to a «godirect» back to our current target if none.

If we wanted to override the behavior above to use the standard target radius instead of the 350 meter value, the following line in a higher level Attack state table would do the trick. Since the first two tokens on the line (M_PROX and '@') are the same as the M_PROX in the target state above, the parser will substitute this transition specification instead.

        M_PROX, '@',  &t, T_NULL, attack,  '%'

Interfacing AI with Mission Objectives

The Mission Objective (MO) code is in charge of notifying the AI engine whenever there is a change in the objective for computer-controlled stars. Whenever a new objective is begun, the MO code sends message to the AI code notifying it of this fact. The AI code then loads new individual tables appropriate to the objective and sends messages putting all Mechs in an initial state appropriate for this objective. This will usually be 'idle' for the leader and 'follow' for followers, with a couple of exceptions. These are 'pushed' messages, so if a Mech is currently engaged in battle he will continue fighting until he has successfully destroyed his target, or is destroyed himself.

Each time a leader Mech is the current gamepiece being processed, he will look at all of the unfinished targets within the current objective and see if he can send someone out of the star to accomplish it. Each objective specifies the number of Mechs to be sent out to any target; the leader will send as many Mechs as he can up to this limit to the first target, and any remaining ones will be sent to the next target, etc. The follower Mech will be put in a state appropriate to the objective and given a new target to operate on.

User-initiated Starmate Orders

If the user has Starmates, he is given the opportunity to

Designer-specified AI Values

In addition to the tables, AI Gamepieces are influenced by values passed in through the gp_spec (see the section on the world loader). These values are: Other values are passed in through the objective table:

Firing Decisions

Whenever a Gamepiece is in 'target' or 'attack' state, he will try to fire at his target. The gunnery skill value, one of the AI Values, determines how often the Gamepiece will attempt to fire. Once he has decided that it is time to fire, he will examine the range of the currently selected weapon and see the range is appropriate to hit his target. If the weapon has the correct range, he will then look to see if the weapon is ready to be fired. If it is, he then looks at the potential heat acquired by firing this weapon. If firing this weapon would not raise his heat level into the danger zone, he will accept that weapon and fire it. Should any of these tests fail, he will cycle to the next weapon and try again, until all weapons have been checked. If he is unable to select a proper weapon, he will not fire on this cycle.

Tactical Maneuvering

Tactical maneuvers are a specific part of the AI which takes over from the general AI at the point when a Mech is within battle range of his opponent, i.e. when the mech has entered «attack» state. The tactical maneuvering code takes control of all the mech's movement functions including throttle, legs rotation, turret rotation, movement direction, and jump jets. Firing decisions are handled separately.

Tactical maneuvers (for brevity, I'll drop the word "Tactical" below) are divided into two successive stages; the approach phase, when a mech is approaching his opponent and may or may not be firing, and the withdrawal phase, when a mech is moving away and may also be firing. There is a group of maneuvers which fall into a third category which is neither approach nor withdrawal. These types of maneuvers (for example circling and behind) are typically handled like withdrawal maneuvers as they are usually followed by an approach maneuver.

When a mech is considering a maneuver, he looks at several factors before making a choice. These include things like the availability of jump-jets or weapons, but the final choice is a random, though sometimes weighted selection from a list of appropriate choices. Every maneuver has a list of the maneuvers which are allowed to follow it, and the final choice comes from that list. These maneuvers, along with their lists of appropriate follow-up maneuvers comprise a maneuver table and there is one maneuver table for each gamepiece class (with the exception of Elementals which are of class GP_MW2MECH but which have their own table). Once a maneuver has been chosen it is executed until completed or until some other circumstance requires termination of that maneuver. The point at which a maneuver is considered complete is dependent on the maneuver, but it is usually based on 1) arrival at a world location, or 2) the expiration of a maneuver timer. A master maneuver timer prevents any maneuver from exceeding a pre-defined maximum duration in case it is unable to reach completion within a reasonable time period.

The following is a list of all current maneuvers. Maneuvers that start with an «a» are approach maneuvers, the ones with a «w» are withdrawal maneuvers, and the remaining ones are neither. Study it. Marvel at it. Then make a really good paper airplane out of it.

Maneuver Descriptions

Piloting Skills

The piloting skill parameter, passed-in as part of the AI values, lets the designer go beyond the basic capabilities inherent in a mech's type to specify, or limit, an individual mech's fighting capabilities. Whereas the Gunnery Skill parameter (a number between 1 and 6) supplied in the gp_spec decides how good a shot a mech is, the piloting skill parameter decides how well a mech maneuvers while engaging another mech. The list below shows what capabilities correspond to what piloting skill values. A value of 3, for example, means that a mech with a piloting of 3 or better (<= 3) will have this capability:

1 - Kamikaze (allows mech to rush his target and explode within damage proximity).
2 - Shot avoidance (can jump out of the way to avoid certain projectile types - currently PPC and guided missiles).
3 - Use jump jets for all turns (speeds up the turning process so AI mechs have more opportunities to fire. Also allows mechs with one leg blown off to still rotate into firing position).
3 - Jump jet maneuvers (shoot from above, DFA, seek from below)
4 - Friendly-fire avoidance. (By turning it off for a mech, he doesn't care if one of his own gets in the way of his weapon).
5 - Turret rotation (if turned off, a mech acts like a beginning player and never use turret swivel. Thus, mechs can fire only when completely facing their target.)
6 - Limited use of ground maneuvers. (use a subset of the normal maneuver list). NOTE: this option is not implemented in the code.

Collision Avoidance

Part of a mech's, or any gamepiece's ability to roam its environment and give the impression that it knows what it's doing is «collision avoidance». When moving gamepieces encounter mountains, other gamepieces, buildings, or crater walls, they must make intelligent choices about how to proceed so that they can carry out their orders. This can be complicated by combat where a gamepiece may be engaged in combat in a confined area with many obstacles. The collision avoidance code is called whenever an AI gamepiece is actually on the ground and moving, and is also used when a human player's mech is in autopilot mode to take control of the navigation. When avoiding an obstacle, the avoidance code takes complete control of the gamepiece navigation system and throttle, and overrides any current behavior.

The collision avoidance algorithm takes the straightforward approach of sending a ray directly out in front of the gamepiece, its length is dependent on ground speed. This dynamic ray length allows fast moving gamepieces with a high closing speed to begin avoiding earlier. Slow moving gamepieces, which don't require as much lead time, use a shorter ray length. This is most beneficial in enclosed, maze-like environments where a longer ray would be easily confused by the abundance of walls.

Changes for Mercenaries AI

For Mechwarrior 2: Mercenaries, the AI will be modified to include additional, more complex personalities over and above the existing ones. In addition to the original clan AI , there will be a new category of AI which will describe individual mechs within the game. This new personality AI is divided into two seperate seperate categories, each specified by a single value. First, the general AI will designate a mech's affiliation and will describe his star's general behavioral traits. Second, the personality AI will further define an individual mech's behavior within the confines of his general AI designation.

Arguments in .WTB files

For new Mercenaries missions, AI personality types will be passed-in via two of the three remaining AI values that are part of the gp_spec. This will free up the gunnery skill parameter to be used for its original purpose of specifying gunnery skill. Implementing these two new AI values will require the modification of WASM, but will not change the format of the .WTB files and therefore won't require the re-WASM'ing of old missions. Please note that Ghost Bear style gp_specs (where the gunnery skill is used to specify a personality) is no longer supported.

New AI Values

AI values 6 and 7 will be used to declare the type of new AI used for a mech. For instance,
gp_spec warhawk whk00std 3 leader internal destroy;defend; 2 250 400 400 2 0 6 "SJ Masakari" ""
has AI value 6 equal to 0 (Clan), and AI value 7 equal to 6 (Veteran Pilot). This means that the format for gp_spec is now
gp_spec <chassis_name> <configuration> <group_id> <authority> <control> <appl_actions> <gunnery_skill> <rubberband_range> <sleep_range> <target_range> <pilot_skill> <affiliation type> <personality> "<target_text>" "<contents_text>" <targeting>

The following conventions will be used to specify AI personalities.

In both cases, gunnery and piloting skill values will be used to specify the mech's gunnery and piloting skill.

The actual values for AI parameters 6 and 7 will be as follows:

The first value, number six, will specify the mech's type. The possible type values are:
0) Clan (default for original Mech II missions)
1) House Troops
2) Irregulars

The second value, number 7, will specify the "Personality AI" type and, as of this writing, will have the following designations:
0) None (default for original Mech II missions)
1) William Tell
2) Green Pilot
3) Leg Shooter
4) Alpha Strike
5) Missile Man
6) Veteran Pilot
7) Floater

New Personality Traits

The new AI variations will be implemented internally by breaking them down into a set of more specific parameters or "traits" which, when combined, will describe the more general personalities. Game designers do not have access to these individual traits. Instead, they will specify the more general personality types using the new AI values as described above. By reducing all peronalities to a smaller set of variables, additional personailties can be implemented as needed to produce a wide variety of behavior. The following "traits" are used to describe all personalities:

General additions

1) Firing code modified to cause firing until a) weapon depleted, or b) hardcoded weapon regeneration time exceeded. After one of these is true, weapon is advanced according to existing flags.

Mercenaries AI Tables

Here are the complete AI tables used in Mechwarrior 2: Mercenaries.